/*
 * Copyright (c) 2016 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.samples.apps.iosched.sync.userdata.util;

import com.google.gson.annotations.SerializedName;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Represents all User specific data that can be synchronized on Google Drive App Data.
 */
public class UserData {
    /** JSON Attribute name of the GCM Key value. */
    public static final String JSON_ATTRIBUTE_GCM_KEY = "gcm_key";

    /** JSON Attribute name of the viewed videos values. */
    public static final String JSON_ATTRIBUTE_VIEWED_VIDEOS = "viewed_videos";

    /** JSON Attribute name of the starred sessions values. */
    public static final String JSON_ATTRIBUTE_STARRED_SESSIONS = "starred_sessions";

    /** JSON Attribute name of the feedback submitted for sessions values. */
    public static final String JSON_ATTRIBUTE_FEEDBACK_SUBMITTED_SESSIONS = "feedback_submitted_sessions";

    /**
     * Used to track whether a session is currently in a user's schedule and the timestamp for when
     * it was last added or removed.
     */
    public static class StarredSession {
        // TODO: make members public. See b/28321953.
        private boolean inSchedule;
        private long timestamp;

        public StarredSession(final boolean inSchedule, final long timestamp) {
            this.inSchedule = inSchedule;
            this.timestamp = timestamp;
        }

        public boolean isInSchedule() {
            return inSchedule;
        }

        public long getTimestamp() {
            return timestamp;
        }

        public void setTimestamp(final long timestamp) {
            this.timestamp = timestamp;
        }

        /**
         * Indicates whether this is equal to another object. Auto-generated by Intellij.
         */
        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            final StarredSession that = (StarredSession) o;

            if (inSchedule != that.inSchedule) {
                return false;
            }
            return timestamp == that.timestamp;

        }

        /**
         * Returns a hash code value for this object. Auto-generated by Intellij.
         */
        @Override
        public int hashCode() {
            int result = (inSchedule ? 1 : 0);
            result = 31 * result + (int) (timestamp ^ (timestamp >>> 32));
            return result;
        }
    }

    // TODO: make members public. See b/28321953.
    @SerializedName(JSON_ATTRIBUTE_STARRED_SESSIONS)
    private Map<String, StarredSession> starredSessions = new HashMap<>();

    @SerializedName(JSON_ATTRIBUTE_FEEDBACK_SUBMITTED_SESSIONS)
    private Set<String> feedbackSubmittedSessionIds = new HashSet<String>();

    @SerializedName(JSON_ATTRIBUTE_VIEWED_VIDEOS)
    private Set<String> viewedVideoIds = new HashSet<String>();

    @SerializedName(JSON_ATTRIBUTE_GCM_KEY)
    private String gcmKey;

    public Map<String, StarredSession> getStarredSessions() {
        return starredSessions;
    }

    public void setStarredSessions(Map<String, StarredSession> starredSessions) {
        this.starredSessions = starredSessions;
    }

    public Set<String> getFeedbackSubmittedSessionIds() {
        return feedbackSubmittedSessionIds;
    }

    public void setFeedbackSubmittedSessionIds(Set<String> feedbackSubmittedSessionIds) {
        this.feedbackSubmittedSessionIds = feedbackSubmittedSessionIds;
    }

    public Set<String> getViewedVideoIds() {
        return viewedVideoIds;
    }

    public void setViewedVideoIds(Set<String> viewedVideoIds) {
        this.viewedVideoIds = viewedVideoIds;
    }

    public String getGcmKey() {
        return gcmKey;
    }

    public void setGcmKey(String gcmKey) {
        this.gcmKey = gcmKey;
    }

    public void addVideoId(String videoId) {
        getViewedVideoIds().add(videoId);
    }

    public void updateVideoIds(UserData other) {
        getViewedVideoIds().addAll(other.getViewedVideoIds());
    }

    public void addFeedbackSubmittedSessionId(String sessionId) {
        getFeedbackSubmittedSessionIds().add(sessionId);
    }

    public void updateFeedbackSubmittedSessionIds(UserData other) {
        getFeedbackSubmittedSessionIds().addAll(other.getFeedbackSubmittedSessionIds());
    }

    /**
     * Indicates whether this is equal to another object. Auto-generated by Intellij.
     */
    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        final UserData userData = (UserData) o;

        if (starredSessions != null ? !starredSessions.equals(userData.starredSessions) :
                userData.starredSessions != null) {
            return false;
        }
        if (feedbackSubmittedSessionIds != null ?
                !feedbackSubmittedSessionIds.equals(userData.feedbackSubmittedSessionIds) :
                userData.feedbackSubmittedSessionIds != null) {
            return false;
        }
        if (viewedVideoIds != null ? !viewedVideoIds.equals(userData.viewedVideoIds) :
                userData.viewedVideoIds != null) {
            return false;
        }
        return !(gcmKey != null ? !gcmKey.equals(userData.gcmKey) : userData.gcmKey != null);

    }

    /**
     * Returns a hash code value for this object. Auto-generated by Intellij.
     */
    @Override
    public int hashCode() {
        int result = starredSessions != null ? starredSessions.hashCode() : 0;
        result = 31 * result +
                (feedbackSubmittedSessionIds != null ? feedbackSubmittedSessionIds.hashCode() :
                        0);
        result = 31 * result + (viewedVideoIds != null ? viewedVideoIds.hashCode() : 0);
        result = 31 * result + (gcmKey != null ? gcmKey.hashCode() : 0);
        return result;
    }
}